import markdown
import re
import json
import time

from django.core import serializers
from django.utils.text import slugify
from django.views.decorators.http import require_POST, require_GET
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage, InvalidPage
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q, F
from django.contrib.auth.models import User
from django.core.mail import EmailMessage, EmailMultiAlternatives
from django.template import loader
from r0Blog.settings import EMAIL_FROM, EMAIL_HOST_USER

from markdown.extensions.toc import TocExtension

from blogApp.models import Post, Category, Tag, Friend, UserExtension
from blogApp.forms import RegisterForm

from comments.forms import CommentForm
from comments.models import sonComment

from blogApp.method import generate_daily_news, increase_like_pk
from utils.oss_utils import get_all_img_url

g_daily_news_list = generate_daily_news()
g_pic_url_list = []

# Create your views here.


class CustomBackend(ModelBackend):
    # 重写authenticate方法
    def authenticate(self, request, username=None, password=None, **kwargs):
        User = get_user_model()
        # Key method
        user = User.objects.filter(
            Q(username=username) | Q(email=username)).first()
        if user:
            if user.check_password(password):
                return user
        return None


def pic_board(request):
    global g_pic_url_list
    if g_pic_url_list:
        ans_list = []
        # ans_list.extend(get_all_img_url("frog/"))
        # ans_list.extend(get_all_img_url("tiny/"))
        ans_list.extend(get_all_img_url("bgk/"))
        ans_list.extend(get_all_img_url("other/"))
        # ans_list[5] = get_all_img_url("tiny/")[0]
        g_pic_url_list = ans_list
        context = {
            "pic_list": g_pic_url_list
        }
    else:
        ans_list = []
        # ans_list.extend(get_all_img_url("frog/"))
        # ans_list.extend(get_all_img_url("tiny/"))
        ans_list.extend(get_all_img_url("bgk/"))
        ans_list.extend(get_all_img_url("other/"))
        # ans_list[5] = get_all_img_url("tiny/")[0]
        g_pic_url_list = ans_list
        context = {
            "pic_list": g_pic_url_list
        }
    return render(request, "pic_board/index.html", context)


@require_GET
def get_g_pic_url_list(request):
    try:
        context = {
            "pic_list": g_pic_url_list
        }
    except Exception as e:
        print(e)
    return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


def color_board(request):
    return render(request, "color_board/index.html")


def color_detail(request, pk):
    print("color" + str(pk))
    context = {
        "pk": pk,
    }
    new_url = "detail/color_detail.html"
    return render(request, new_url, context)


def index(request):
    # request.session.setdefault('style_flag', -1)
    # p=int(p)
    post_list = Post.objects.all().order_by('-created_time')
    """根据创建时间，倒序"""
    paginator = Paginator(post_list, 10)
    if request.method == "GET":
        # 获取 url 后面的 page 参数的值, 首页不显示 page 参数, 默认值是 1
        page = request.GET.get('page')
        try:
            post_list = paginator.page(page)
        # todo: 注意捕获异常
        except PageNotAnInteger:
            # 如果请求的页数不是整数, 返回第一页。
            post_list = paginator.page(1)
        except EmptyPage:
            # 如果请求的页数不在合法的页数范围内，返回结果的最后一页。
            post_list = paginator.page(paginator.num_pages)
        except InvalidPage:
            # 如果请求的页数不存在, 重定向页面
            return HttpResponse('找不到页面的内容')
    context = {
        "title": "r0Blog",
        "post_list": post_list,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    return render(request, 'blog/index.html', context)


@require_POST
def get_daily_news_list(request):

    context = {
        "post_list": serializers.serialize("json", g_daily_news_list)
    }
    return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


@require_POST
def news_like(request, pk):
    global g_daily_news_list
    link_cnt = increase_like_pk(pk)
    g_daily_news_list = generate_daily_news()
    context = {
        "news_like_cnt": link_cnt
    }
    return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


@require_POST
def register_user(request):
    regis = RegisterForm(request.POST)
    if regis.is_valid():
        check_name_user = User.objects.filter(
            Q(username=request.POST.get('name'))).first()
        if check_name_user:
            context = {
                'username_error': '请爬，有这个名字了！',
            }
            return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')
        else:
            pass

        check_email_user = User.objects.filter(
            Q(email=request.POST.get('email'))).first()
        if check_email_user:
            context = {
                'email_error': '请爬，有这个邮箱了！',
            }
            return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')
        else:
            pass

        key_user = User.objects.create_user(username=request.POST.get('name'), password=request.POST.get('password'),
                                            email=request.POST.get('email'))
        new_user = regis.save(commit=False)
        # key_user.extension.qqnumber=request.POST.get('qqnumber')
        # key_user.extension.url=request.POST.get('url')
        new_user.user = key_user
        # key_user.save()
        new_user.save()
        print("regis success")
        send_register_email(request.POST.get('email'),
                            request.POST.get('name'))
        re_context = {
            "name": request.POST.get("name"),
            "title": "阿凌的猫爬架",
            "body": "注册成功啦！"
        }
        send_myself_email("1654262479@qq.com", re_context)
        return HttpResponse("")
    else:
        context = {
            'username_error': regis.errors.get('name'),
            'email_error': regis.errors.get('email'),
            'url_error': regis.errors.get('url'),
            'qq_error': regis.errors.get('qqnumber'),
            'picurl_error': regis.errors.get('picurl'),
        }
        print("regis fail")
        return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


def logout_user(request):
    logout(request)
    return redirect('blog:index')


def login_page(request):
    return render(request, 'blog/register_login.html')


@require_POST
def login_user(request):
    message = ""
    if request.user.is_authenticated:
        return HttpResponse("")
    else:
        user_email = request.POST.get('email')
        user_password = request.POST.get('password')
        user_auth = authenticate(
            request, username=user_email, password=user_password)
        if user_auth is not None:
            login(request, user_auth)
            print("login yes")
            return HttpResponse("")
        else:
            message = "邮箱/用户不存在或密码错误。"
            print("login fail")
            context = {
                'message': message
            }
            return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


@require_POST
def post_info(request):
    post_title = request.POST.get("post_title")

    post = Post.objects.filter(Q(title=post_title)).first()
    if post:
        print("search success")
        tag_list = []
        for tag in post.tags.all():
            tag_list.append(tag.name)
            print(tag.name)
        context = {
            "title": post_title,
            "author": post.author.username,
            "cate": post.category.name,
            "creat_time": post.created_time.strftime('%Y-%m-%d %H：%M'),
            "tag_list": tag_list,
            "g_daily_news_status_list": [it.status for it in g_daily_news_list]
        }
        return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')
    else:
        return HttpResponse("")


@require_POST
def post_cd(request):
    post_title = request.POST.get("post_title")
    post = Post.objects.filter(Q(title=post_title)).first()
    if post:
        tmp = post.get_absolute_url()
        print(tmp)
        context = {
            "success_url": tmp
        }
        return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')

    else:
        return HttpResponse("")


@require_POST
def post_all(request):
    posts = Post.objects.all().order_by('-created_time')
    post_list = []
    for post in posts:
        tmp = {
            "title": post.title,
            "category": post.category.name
        }
        post_list.append(tmp)
    if len(post_list) != 0:
        context = {
            "post_list": post_list,
            "g_daily_news_status_list": [it.status for it in g_daily_news_list]
        }
        return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')
    else:
        return HttpResponse("")


def detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    # 阅读量 +1
    post.increase_views()
    # 记得在顶部导入 CommentForm
    form = CommentForm()
    # 获取这篇 post 下的全部评论
    comment_list = post.comment_set.all()
    md = markdown.Markdown(extensions=[
        'markdown.extensions.extra',
        'markdown.extensions.toc',
        TocExtension(slugify=slugify),
    ])
    for comment in comment_list:
        comment.sonComment_list = sonComment.objects.filter(
            p_comment=comment).order_by('-created_time')
        # comment.text=md.convert(comment.text)

    post.body = md.convert(post.body)
    post.body = post.body.replace("\r\n", ' \n')
    post.body = post.body.replace("\u200b", "")
    # post.body=post.body.replace("<p><code>","<pre class=\"code-box\"><div class=\"code-type\"></div><code>")
    # post.body=post.body.replace("<p> <code>","<pre class=\"code-box\"><div class=\"code-type\"></div><code>")
    # post.body=post.body.replace("</code></p>","</code></pre>")
    # post.body=post.body.replace("</code> </p>","</code></pre>")
    m = re.search(r'<div class="toc">\s*<ul>(.*)</ul>\s*</div>', md.toc, re.S)
    post.toc = m.group(1) if m is not None else ''
    context = {
        'post': post,
        'comment_list': comment_list,
        'tmp_use': 0,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    # 上一篇，找出id小于当前文章id的文章，降序排序后取第一个，即为上一篇
    # gt(gte): 大于(大于等于) lt小于(小于等于)
    # django内置的查询字段,语法为字段 + 两条下划线 + 内置查询字段：field__bulit-in
    prev_post = Post.objects.filter(id__lt=pk).order_by("-id")[:1]
    if len(prev_post) == 0:
        context['prev_post'] = 0
    else:
        for prev_p in prev_post:
            context['prev_post'] = prev_p
    # 下一篇，找出id大于当前文章id的文章,升序排序后取第一个，即为下一篇
    next_post = Post.objects.filter(id__gt=pk).order_by("id")[:1]
    if len(next_post) == 0:
        context['next_post'] = 0
    else:
        for next_p in next_post:
            context['next_post'] = next_p

    return render(request, 'blog/detail.html', context)


def archive(request):
    posts_list = []
    date_list = Post.objects.dates('created_time', 'month', order='DESC')
    tag_list = Tag.objects.all()
    index = 0
    for date in date_list:
        posts = Post.objects.filter(created_time__year=date.year,
                                    created_time__month=date.month
                                    ).order_by('-created_time')
        posts.year = date.year
        posts.month = date.month
        posts_list.append(posts)
    context = {
        'posts_list': posts_list,
        'date_list': date_list,
        'tag_list': tag_list,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    return render(request, 'blog/inclusions/_archives.html', context)


def category(request, name):
    # 记得在开始部分导入 Category 类
    cate = get_object_or_404(Category, name=name)
    post_list = Post.objects.filter(category=cate).order_by('-created_time')
    context = {
        'post_list': post_list,
        'name': name,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    # send_register_email("boogieling_o@163.com")
    return render(request, 'blog/inclusions/_categories.html', context)


def tag(request, name):
    # 记得在开始部分导入 Tag 类
    t = get_object_or_404(Tag, name=name)
    post_list = Post.objects.filter(tags=t).order_by('-created_time')
    context = {
        'post_list': post_list,
        'name': name,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    return render(request, 'blog/inclusions/_tags.html', context)


def friend(request):
    friend_list = Friend.objects.all().order_by('-created_time')
    context = {
        'friend_list': friend_list,
        "g_daily_news_status_list": [it.status for it in g_daily_news_list]
    }
    return render(request, 'blog/inclusions/_friend_link.html', context)


def about_me(request):
    context = {
        "cur_time": time.strftime('%H:%M:%S', time.localtime(time.time()))
    }
    return render(request, 'blog/about.html', context)


def cat_page(request):
    return render(request, 'cat.html')


def send_register_email(email, name):
    # 实例化EmailVerifyRecord对象，将邮件内容保存到数据库，便于查询激活链接是否存在
    # email_record = EmailVerifyRecord()
    # email_record.email = email
    # email_record.send_type = send_type
    # email_record.code = random_str(20) #生成长20的随机字符串用以构成激活链接(域名/active/随机code/)
    # 只要编写逻辑判断激活链接中的code是否有，就可以对应user的is_active=true
    # email_record.save()

    # 发送邮件功能如下
    # email_title = ""邮件标题
    # email_body = ""主体

    # email_subject = '你好，我是阿凌///” v "///'
    # email_content = ""
    # emaillist = [email]     # 收件人列表
    # email = EmailMessage(email_subject, email_content, EMAIL_HOST_USER, emaillist) # 创建email对象
    # email.content_subtype = 'html'    # 设置email的内容
    # send_status =email.send(fail_silently=True)    # If it’s False, send_mail will raise an smtplib.SMTPException
    # print(send_status)

    # 发送的html模板的名称
    context = {
        "name": name
    }
    email_template_name = 'email_tmp_1.html'
    t = loader.get_template(email_template_name)
    html_content = t.render(context)
    msg = EmailMultiAlternatives(
        "哟，是阿凌", html_content, EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")
    send_status = msg.send()
    print("send status:", end="")
    print(send_status)


def send_myself_email(email, re_context):
    email_template_name = 'email_tmp_2.html'
    t = loader.get_template(email_template_name)
    html_content = t.render(re_context)
    msg = EmailMultiAlternatives(
        "哟，是我自己", html_content, EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")
    send_status = msg.send()
    print("send status: {0}".format(send_status), end="")


@require_POST
def check_style(request):
    request.session.setdefault('style_flag', "-1")
    context = {
        "flag": request.session['style_flag']
    }
    print(request.session['style_flag'])
    return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')


@require_POST
def chang_style(request):
    if not request.session['style_flag'] is None:
        request.session['style_flag'] = request.POST.get('style')
    else:
        request.session['style_flag'] = -1
    context = {
        "flag": request.session['style_flag']
    }
    return HttpResponse(json.dumps(context, ensure_ascii=False), content_type='application/json')
